package p.sglmsn.top.antiduplication.annotation;

import org.springframework.lang.Nullable;
import p.sglmsn.top.antiduplication.handle.DuplicateRequestFiltering;
import p.sglmsn.top.antiduplication.handle.DuplicateRequestFilteringResponseHandle;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 防止重复提交
 * 请求后处理查
 * {@link DuplicateRequestFilteringResponseHandle}
 * <p>
 * <p>
 * 通用处理查
 * {@link DuplicateRequestFiltering}
 *
 * @author 王涛
 * @date 2020/12/03
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AntiDuplication {

    /**
     * 防重复生效时的提示信息
     *
     * @return {@link String}
     */
    String msg() default "该请求已受理,请勿重复点击";

    /**
     * 可请求次数
     *
     * @return long
     */
    @Deprecated
    long count() default 1;

    /**
     * 多久内只能访问一次
     * {@link AntiDuplicationType#带时效的过滤}
     *
     * @return long  毫秒
     */
    long time() default 1000 * 30;

    /**
     * 未实现,本意是在{@link DuplicateRequestFiltering#postHandle(HttpServletRequest, HttpServletResponse, Object, org.springframework.web.servlet.ModelAndView)}调用
     *
     * @return {@link Class<? extends Handle>[]}
     */
    @Deprecated
    Class<? extends Handle>[] handle() default {};

    /**
     * 返回之前操作
     * 当需要根据<b>返回值</b>来判断是否需要清除防重复提交状态的时候有用.
     * {@link DuplicateRequestFilteringResponseHandle#beforeBodyWrite(Object, org.springframework.core.MethodParameter, org.springframework.http.MediaType, Class, org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse)}
     *
     * @return {@link Class<? extends BeforeBodyWrite>[]}
     */
    Class<? extends BeforeBodyWrite>[] beforeBodyWrite() default {};


    /**
     * 过滤类型
     *
     * @return {@link AntiDuplicationType}
     */
    AntiDuplicationType type() default AntiDuplicationType.带时效的过滤;


    /**
     * 防重复类型
     *
     * @author Administrator
     * @date 2020/12/04
     */
    enum AntiDuplicationType {

        /**
         * 散列过滤  没写
         */
        @Deprecated
        hash过滤,
        /**
         * url过滤   ,当用户上一个该url请求没走完时拒绝,{@link AntiDuplication#time()} 超时
         */
        url过滤,
        /**
         * {@link AntiDuplication#time()} 内 防止重复请求
         */
        带时效的过滤,

        无效过滤


    }

    /**
     * 请求结束之后的处理对象
     *
     * @author 王涛
     * @date 2021/02/01 10:39
     */
    interface Handle {
        /**
         * 调用
         * {@link DuplicateRequestFiltering#afterCompletion(HttpServletRequest, HttpServletResponse, Object, Exception)}
         * 时会执行
         *
         * @param request  请求
         * @param response 响应
         * @param handler  处理程序
         * @param ex       异常
         */
        default void handle(HttpServletRequest request, HttpServletResponse response, Object handler,
                            @Nullable Exception ex) {

        }
    }

    /**
     * 请求返回之前做操作
     * <p>
     * {@link DuplicateRequestFilteringResponseHandle#beforeBodyWrite(Object, org.springframework.core.MethodParameter, org.springframework.http.MediaType, Class, org.springframework.http.server.ServerHttpRequest, org.springframework.http.server.ServerHttpResponse)}
     *
     * @author 王涛
     * @date 2021/02/01 11:11
     */
    interface BeforeBodyWrite {
        default Object handle(Object body) {
            return body;
        }
    }


}